Implement guest_access routines for copying to/from a sub-field of a structure.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 8 Mar 2006 14:39:59 +0000 (15:39 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 8 Mar 2006 14:39:59 +0000 (15:39 +0100)
Use this as part of a tidy-up of the multicall hypercall.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/common/multicall.c
xen/include/asm-ia64/guest_access.h
xen/include/asm-x86/guest_access.h

index 16e2fc1a1c75ce12e7c94394b51d69ab8d968e73..500bb38e869ce405025ff5109b9e08d7535b4705 100644 (file)
@@ -34,7 +34,10 @@ do_multicall(
 
     for ( i = 0; i < nr_calls; i++ )
     {
-        if ( unlikely(__copy_from_guest_offset(&mcs->call, call_list, i, 1)) )
+        if ( hypercall_preempt_check() )
+            goto preempted;
+
+        if ( unlikely(__copy_from_guest(&mcs->call, call_list, 1)) )
             goto fault;
 
         do_multicall_call(&mcs->call);
@@ -47,33 +50,21 @@ do_multicall(
              */
             struct multicall_entry corrupt;
             memset(&corrupt, 0xAA, sizeof(corrupt));
-            (void)__copy_to_guest_offset(call_list, i, &corrupt, 1);
+            (void)__copy_to_guest(call_list, &corrupt, 1);
         }
 #endif
 
-        if ( unlikely(__copy_to_guest_offset(call_list, i, &mcs->call, 1)) )
+        if ( unlikely(__copy_field_to_guest(call_list, &mcs->call, result)) )
             goto fault;
 
-        if ( hypercall_preempt_check() )
+        if ( test_bit(_MCSF_call_preempted, &mcs->flags) )
         {
-            /*
-             * Copy the sub-call continuation if it was preempted.
-             * Otherwise skip over the sub-call entirely.
-             */
-            if ( !test_bit(_MCSF_call_preempted, &mcs->flags) )
-                i++;
-            else
-                (void)__copy_to_guest_offset(call_list, i, &mcs->call, 1);
-
-            /* Only create a continuation if there is work left to be done. */
-            if ( i < nr_calls )
-            {
-                mcs->flags = 0;
-                guest_handle_add_offset(call_list, i);
-                return hypercall_create_continuation(
-                    __HYPERVISOR_multicall, "hi", call_list, nr_calls-i);
-            }
+            /* Copy the sub-call continuation. */
+            (void)__copy_to_guest(call_list, &mcs->call, 1);
+            goto preempted;
         }
+
+        guest_handle_add_offset(call_list, 1);
     }
 
     mcs->flags = 0;
@@ -82,6 +73,11 @@ do_multicall(
  fault:
     mcs->flags = 0;
     return -EFAULT;
+
+ preempted:
+    mcs->flags = 0;
+    return hypercall_create_continuation(
+        __HYPERVISOR_multicall, "hi", call_list, nr_calls-i);
 }
 
 /*
index 61ed20a12c8eab4906e7fb212eebd02866ed574f..f0f4a0816050e0a31e7c01b4fd043842ac31b16f 100644 (file)
     copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));     \
 })
 
+/* Copy sub-field of a structure to guest context via a guest handle. */
+#define copy_field_to_guest(hnd, ptr, field) ({         \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    copy_to_user(_x, _y, sizeof(*_x));                  \
+})
+
+/* Copy sub-field of a structure from guest context via a guest handle. */
+#define copy_field_from_guest(ptr, hnd, field) ({       \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    copy_from_user(_y, _x, sizeof(*_x));                \
+})
+
 /*
  * Pre-validate a guest handle.
  * Allows use of faster __copy_* functions.
     __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));   \
 })
 
+#define __copy_field_to_guest(hnd, ptr, field) ({       \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    __copy_to_user(_x, _y, sizeof(*_x));                \
+})
+
+#define __copy_field_from_guest(ptr, hnd, field) ({     \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    __copy_from_user(_y, _x, sizeof(*_x));              \
+})
+
 #endif /* __ASM_IA64_GUEST_ACCESS_H__ */
index 4b75af5bee266b53ee76c25b81debf368b75e4e0..b9258e095309c8931bb740966e31ece6f2164b84 100644 (file)
     copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));     \
 })
 
+/* Copy sub-field of a structure to guest context via a guest handle. */
+#define copy_field_to_guest(hnd, ptr, field) ({         \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    copy_to_user(_x, _y, sizeof(*_x));                  \
+})
+
+/* Copy sub-field of a structure from guest context via a guest handle. */
+#define copy_field_from_guest(ptr, hnd, field) ({       \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    copy_from_user(_y, _x, sizeof(*_x));                \
+})
+
 /*
  * Pre-validate a guest handle.
  * Allows use of faster __copy_* functions.
     __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr));   \
 })
 
+#define __copy_field_to_guest(hnd, ptr, field) ({       \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    __copy_to_user(_x, _y, sizeof(*_x));                \
+})
+
+#define __copy_field_from_guest(ptr, hnd, field) ({     \
+    const typeof(&(ptr)->field) _x = &(hnd).p->field;   \
+    const typeof(&(ptr)->field) _y = &(ptr)->field;     \
+    __copy_from_user(_y, _x, sizeof(*_x));              \
+})
+
 #endif /* __ASM_X86_GUEST_ACCESS_H__ */